package com.emin.platform.productCenter.multidatasource;

import com.emin.platform.productCenter.util.PltThreadLocalUtil;
import org.apache.log4j.Logger;
import org.hibernate.*;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.stat.Statistics;
import org.springframework.stereotype.Component;

import javax.naming.NamingException;
import javax.naming.Reference;
import java.sql.Connection;
import java.util.*;
import java.util.Map.Entry;

/**
 * 此类用于获取SessionFactory
 *
 * @author Jack
 * @version V1.0
 * @Description: 此类用于获取SessionFactory，创建好的SessionFactory保存在sessionFactories中
 * @date 2017/10/24 14:42
 */
@Component
public class MultiSessionFactory implements SessionFactory {
    private static final long serialVersionUID = 4797681003913933339L;

    // 存储已经创建好的SessionFactory
    private static Map<Long, SessionFactory> sessionFactories;
    private final transient Logger logger = Logger.getLogger(MultiSessionFactory.class);
    // 单例
    private static MultiSessionFactory multiSessionFactory = new MultiSessionFactory();

    private MultiSessionFactory() {
        sessionFactories = new HashMap();
    }

    public static MultiSessionFactory getInstance() {
        return multiSessionFactory;
    }

    public void putSessionFactory(Long dataSourceKey, SessionFactory sessionFactory) {
        this.logger.info("put sessionFactory<data source key:" + dataSourceKey + "> ");
        sessionFactories.put(dataSourceKey, sessionFactory);
        System.out.println(sessionFactories.toString());
    }

    public void removeSessionFactory(Long dataSourceKey) {
        this.logger.info("remove sessionFactory<data source key:" + dataSourceKey + "> ");
        sessionFactories.remove(dataSourceKey);
    }

    /**
     * 获取SessionFactory
     *
     * @return void
     * @throws
     * @author Jack
     * @date 2017/10/24
     */
    public SessionFactory getSessionFactory() {
        Long companyId = this.getCompanyId();
        return this.getSessionFactory(companyId);
    }

    /**
     * 获取SessionFactory
     *
     * @return void
     * @throws
     * @author Jack
     * @date 2017/10/24
     */
    public SessionFactory getSessionFactory(Long companyId) {
        SessionFactory sessionFactory = (SessionFactory) sessionFactories.get(companyId);
        this.logger.info("get sessionFactory<data source key :" + companyId + "> ");
        if (sessionFactory == null) {
            this.logger.warn("There is no sessionFactory <data source key :" + companyId + ">" +
                    " !");
        }
        return sessionFactory;
    }

    public Collection<SessionFactory> getAllSessionFactory() {
        return sessionFactories.values();
    }

    public Set<Long> getSessionFactoryKeys() {
        return sessionFactories.keySet();
    }

    private Long getCompanyId() {
        return PltThreadLocalUtil.getCompanyId();
    }

    public SessionFactoryOptions getSessionFactoryOptions() {
        return this.getSessionFactory().getSessionFactoryOptions();
    }

    public SessionBuilder withOptions() {
        return this.getSessionFactory().withOptions();
    }

    public Session openSession() throws HibernateException {
        return this.getSessionFactory().openSession();
    }

    public Session getCurrentSession() throws HibernateException {
        return this.getSessionFactory().getCurrentSession();
    }

    public StatelessSessionBuilder withStatelessOptions() {
        return this.getSessionFactory().withStatelessOptions();
    }

    public StatelessSession openStatelessSession() {
        return this.getSessionFactory().openStatelessSession();
    }

    public StatelessSession openStatelessSession(Connection connection) {
        return this.getSessionFactory().openStatelessSession(connection);
    }

    public ClassMetadata getClassMetadata(Class entityClass) {
        return this.getSessionFactory().getClassMetadata(entityClass);
    }

    public ClassMetadata getClassMetadata(String entityName) {
        return this.getSessionFactory().getClassMetadata(entityName);
    }

    public CollectionMetadata getCollectionMetadata(String roleName) {
        return this.getSessionFactory().getCollectionMetadata(roleName);
    }

    public Map<String, ClassMetadata> getAllClassMetadata() {
        return this.getSessionFactory().getAllClassMetadata();
    }

    public Map getAllCollectionMetadata() {
        return this.getSessionFactory().getAllClassMetadata();
    }

    public Statistics getStatistics() {
        return this.getSessionFactory().getStatistics();
    }

    public void close() throws HibernateException {
        Set<Entry<Long, SessionFactory>> factoryEntries = sessionFactories.entrySet();
        Iterator var2 = factoryEntries.iterator();
        while (var2.hasNext()) {
            Entry<Long, SessionFactory> entry = (Entry) var2.next();
            SessionFactory sessionFactory = (SessionFactory) entry.getValue();
            sessionFactory.close();
        }
        factoryEntries = null;
    }

    public boolean isClosed() {
        return this.getSessionFactory().isClosed();
    }

    public Cache getCache() {
        return this.getSessionFactory().getCache();
    }

    public Set getDefinedFilterNames() {
        return this.getSessionFactory().getDefinedFilterNames();
    }

    public FilterDefinition getFilterDefinition(String filterName) throws HibernateException {
        return this.getSessionFactory().getFilterDefinition(filterName);
    }

    public boolean containsFetchProfileDefinition(String name) {
        return this.getSessionFactory().containsFetchProfileDefinition(name);
    }

    public TypeHelper getTypeHelper() {
        return this.getSessionFactory().getTypeHelper();
    }

    public Reference getReference() throws NamingException {
        return this.getSessionFactory().getReference();
    }
}
